package org.mx.service.server.websocket;

import org.mx.StringUtils;
import org.mx.service.server.jmx.WebsocketServer;
import org.mx.spring.utils.SpringContextHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 描述： 默认的Websocket session生命周期监控器实现。
 *
 * @author John.Peng Date time 2018/3/10 上午10:56
 */
public class WsLifeCircleMonitor implements WsLifeCircle {
	private static final Logger logger = LoggerFactory.getLogger(WsLifeCircleMonitor.class);

	private String path = "/";

	/**
	 * 默认的构造函数
	 */
	public WsLifeCircleMonitor() {
		super();
	}

	/**
	 * 构造函数
	 *
	 * @param path Websocket监听路径
	 */
	public WsLifeCircleMonitor(String path) {
		this();
		this.path = path;
	}

	/**
	 * {@inheritDoc}
	 *
	 * @see WsLifeCircle#getPath()
	 */
	@Override
	public String getPath() {
		if (StringUtils.isBlank(path)) {
			// 默认为根路径
			return "/";
		} else {
			// 如果没有以"/"开头，自动拼上
			return path.startsWith("/") ? path : String.format("/%s", path);
		}
	}

	/**
	 * {@inheritDoc}
	 *
	 * @see WsLifeCircle#afterClose(WsConnectKey, int, String)
	 */
	@Override
	public void afterConnect(WsConnectKey connectKey) {
		if (logger.isDebugEnabled()) {
			logger.debug(String.format("After connect: %s.", connectKey.toString()));
		}
		try {
			WebsocketServer websocketServerMXBean = SpringContextHolder.getBean(WebsocketServer.class);
			if (websocketServerMXBean != null) {
				websocketServerMXBean.sessionChange(path, 1);
			}
		} catch (Exception ex) {
			// 由于很大概率可能没有配置JMX监控，因此这里的错误作为trace日志记录。
			if (logger.isTraceEnabled()) {
				logger.trace("The WebsocketServerMXBean not defined.");
			}
		}
	}
	
	/**
	 * {@inheritDoc}
	 *
	 * @see WsLifeCircle#beforeClose(WsConnectKey)
	 */
	@Override
	public void beforeClose(WsConnectKey connectKey) {
		if (logger.isDebugEnabled()) {
			logger.debug(String.format("Before close: %s.", connectKey.toString()));
		}
	}

	/**
	 * {@inheritDoc}
	 *
	 * @see WsLifeCircle#afterClose(WsConnectKey, int, String)
	 */
	@Override
	public void afterClose(WsConnectKey connectKey, int code, String reason) {
		if (logger.isDebugEnabled()) {
			logger.debug(String.format("After close: %s, code: %d, reason: %s.", connectKey.toString(), code, reason));
		}
		try {
			WebsocketServer websocketServerMXBean = SpringContextHolder.getBean(WebsocketServer.class);
			if (websocketServerMXBean != null) {
				websocketServerMXBean.sessionChange(path, -1);
			}
		} catch (Exception ex) {
			// 由于很大概率可能没有配置JMX监控，因此这里的错误作为trace日志记录。
			if (logger.isTraceEnabled()) {
				logger.trace("The WebsocketServerMXBean not defined.");
			}
		}
	}

	/**
	 * {@inheritDoc}
	 *
	 * @see WsLifeCircle#hasError(WsConnectKey, Throwable)
	 */
	@Override
	public void hasError(WsConnectKey connectKey, Throwable throwable) {
		if (logger.isDebugEnabled()) {
			logger.debug(String.format("Has any error: %s.", connectKey.toString()), throwable);
		}
		try {
			WebsocketServer websocketServerMXBean = SpringContextHolder.getBean(WebsocketServer.class);
			if (websocketServerMXBean != null) {
				websocketServerMXBean.errorChange(path, 1);
			}
		} catch (Exception ex) {
			// 由于很大概率可能没有配置JMX监控，因此这里的错误作为trace日志记录。
			if (logger.isTraceEnabled()) {
				logger.trace("The WebsocketServerMXBean not defined.");
			}
		}
	}

	/**
	 * {@inheritDoc}
	 *
	 * @see WsLifeCircle#hasText(WsConnectKey, String)
	 */
	@Override
	public void hasText(WsConnectKey connectKey, String text) {
		if (logger.isDebugEnabled()) {
			logger.debug(String.format("Receive a text message: %s, message: %s.", connectKey.toString(), text));
		}
		try {
			WebsocketServer websocketServerMXBean = SpringContextHolder.getBean(WebsocketServer.class);
			if (websocketServerMXBean != null) {
				websocketServerMXBean.messageChange(path, 1);
			}
		} catch (Exception ex) {
			// 由于很大概率可能没有配置JMX监控，因此这里的错误作为trace日志记录。
			if (logger.isTraceEnabled()) {
				logger.trace("The WebsocketServerMXBean not defined.");
			}
		}
	}

	/**
	 * {@inheritDoc}
	 *
	 * @see WsLifeCircle#hasBinary(WsConnectKey, byte[])
	 */
	@Override
	public void hasBinary(WsConnectKey connectKey, byte[] buffer) {
		if (logger.isDebugEnabled()) {
			logger.debug(String.format("Receive a binary message: %s, total: %d bytes.", connectKey.toString(),
					buffer.length));
		}
		try {
			WebsocketServer websocketServerMXBean = SpringContextHolder.getBean(WebsocketServer.class);
			if (websocketServerMXBean != null) {
				websocketServerMXBean.messageChange(path, 1);
			}
		} catch (Exception ex) {
			// 由于很大概率可能没有配置JMX监控，因此这里的错误作为trace日志记录。
			if (logger.isTraceEnabled()) {
				logger.trace("The WebsocketServerMXBean not defined.");
			}
		}
	}
}
